package org.marsdonne.auth;

import org.marsdonne.archives.Client;
import org.marsdonne.archives.Platform;
import org.marsdonne.archives.OrganizationType;
import org.springframework.data.jpa.repository.JpaRepository;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;

public interface EndPointUserRepos extends JpaRepository<EndPointUser, Long>, AggregateUser {
    Optional<EndPointUser> findByIdentifier(String identifier);

    Optional<EndPointUser> findByIdentifierAndPlatformAndClient(String identifier, Platform platform, Client client);

    List<EndPointUser> findAllByUnionUser(UnionUser unionUser);

    @Transactional
    default EndPointUser bind(Client client, Platform platform, String identifier, String secretCode, String nickname) {
        EndPointUser endPointUser = null;

        Optional<EndPointUser> optionalEndPointUser = this.findByIdentifierAndPlatformAndClient(identifier, platform, client);
        if (optionalEndPointUser.isPresent()) {
            endPointUser = optionalEndPointUser.get();
            endPointUser.setSecretCode(secretCode);
        } else {
            endPointUser = new EndPointUser(client, platform, identifier, secretCode, nickname);
        }

        return this.save(endPointUser);
    }

    @Transactional
    default PlatformUser bind(String identifier, Platform platform, String platformId, String phoneNumber, String invoiceTitle) {
        PlatformUser platformUser = null;
        Optional<EndPointUser> optionalEndPointUser = this.findByIdentifier(identifier);

        if (optionalEndPointUser.isPresent()) {
            EndPointUser endPointUser = optionalEndPointUser.get();
            platformUser = this.bind(endPointUser, platform, platformId, phoneNumber, invoiceTitle);

            if (endPointUser.getPlatformUser() == null) {
                endPointUser.setPlatformUser(platformUser);
                this.save(endPointUser);
            }
        }

        return platformUser;
    }

    @Transactional
    default Optional<EndPointUser> bind(String identifier, String realName, String residentId, OrganizationType organizationType, Long organizationId, String organizationLicenseCode, String organizationName) {
        Optional<EndPointUser> optionalEndPointUser = this.findByIdentifier(identifier);
        if (optionalEndPointUser.isPresent()) {
            EndPointUser endPointUser = optionalEndPointUser.get();

            Optional<UnionUser> optionalUnionUser = this.bind(realName, residentId, organizationType, organizationId, organizationLicenseCode, organizationName);

            if (optionalUnionUser.isPresent()) {
                endPointUser.setUnionUser(optionalUnionUser.get());
            }

            return Optional.ofNullable(save(endPointUser));
        }
        return Optional.empty();
    }

    @Transactional
    default UnionUser certifyUser(String identifier, String residentId, String realName) {
        UnionUser unionUser = null;

        Optional<EndPointUser> optionalEndPointUser = this.findByIdentifier(identifier);

        if (optionalEndPointUser.isPresent()) {
            EndPointUser endPointUser = optionalEndPointUser.get();
            unionUser = this.certifyUser(endPointUser, residentId, realName);
            endPointUser.setUnionUser(unionUser);
            this.save(endPointUser);
        }

        return unionUser;
    }

    @Transactional
    default Optional<EndPointUser> updateAvatarUrl(String identifier, String avatarUrl) {
        Optional<EndPointUser> optionalEndPointUser = this.findByIdentifier(identifier);

        if (optionalEndPointUser.isPresent()) {
            EndPointUser endPointUser = optionalEndPointUser.get();
            endPointUser.setAvatarUrl(avatarUrl);

            return Optional.ofNullable(this.save(endPointUser));
        }

        return Optional.empty();
    }

    @Transactional
    default Optional<EndPointUser> updateNickname(String identifier, String nickName) {
        Optional<EndPointUser> optionalEndPointUser = this.findByIdentifier(identifier);

        if (optionalEndPointUser.isPresent()) {
            EndPointUser endPointUser = optionalEndPointUser.get();
            endPointUser.setNickname(nickName);

            return Optional.ofNullable(this.save(endPointUser));
        }

        return Optional.empty();
    }
}
